package com.alibaba.algo.apiimpl.user;

import java.util.concurrent.TimeUnit;

import javax.annotation.Resource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import com.alibaba.algo.util.StringUtil;
import com.alibaba.fastjson.JSON;
import com.dingtalk.api.DefaultDingTalkClient;
import com.dingtalk.api.DingTalkClient;
import com.dingtalk.api.request.OapiGettokenRequest;
import com.dingtalk.api.request.OapiSnsGetuserinfoBycodeRequest;
import com.dingtalk.api.request.OapiUserGetbyunionidRequest;
import com.dingtalk.api.request.OapiV2UserGetRequest;
import com.dingtalk.api.response.OapiGettokenResponse;
import com.dingtalk.api.response.OapiSnsGetuserinfoBycodeResponse;
import com.dingtalk.api.response.OapiUserGetbyunionidResponse;
import com.dingtalk.api.response.OapiV2UserGetResponse;
import com.dingtalk.api.response.OapiV2UserGetResponse.UserGetResponse;
import com.taobao.api.ApiException;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
public class DingService {
	@Resource
	private Environment env;
	@Autowired
	private StringRedisTemplate stringRedisTemplate;

	public UserGetResponse getUserGetResponse(String code) {
		String appkey = env.getProperty("ding.appkey");
		String appSecret = env.getProperty("ding.appSecret");
		String loginAppkey = env.getProperty("ding.login.appkey");
		String loginAppSecret = env.getProperty("ding.login.appSecret");
		if (StringUtil.isEmptyAny(appkey, appSecret, loginAppkey, loginAppSecret)) {
			return null;
		}
		String unionid = getUnionid(code, loginAppkey, loginAppSecret);// 获取钉钉unionid
		if (StringUtil.isEmpty(unionid)) {
			return null;
		}
		// 获取接口调用凭证
		String dingToken = getToken(appkey, appSecret);
		if (StringUtil.isEmpty(dingToken)) {
			return null;
		}
		String dingUserId = getUserId(unionid, dingToken);// 获取钉钉用户id
		if (StringUtil.isEmpty(dingUserId)) {
			return null;
		}
		UserGetResponse userGetResponse = getUserGetResponse(dingUserId, dingToken);// 钉钉用户信息
		log.info("钉钉用户标识：{},钉钉用户信息：{}", dingUserId, JSON.toJSONString(userGetResponse));
		return userGetResponse;
	}

	/**
	 * @Description: 获取钉钉接口token(access_token的有效期为7200秒（2小时）)
	 * @author: malin
	 * @date: 2021年3月9日 下午2:51:52
	 */
	private String getToken(String appkey, String appSecret) {
		String redisTokenKey = "sso:ding:" + appkey;
		String token = stringRedisTemplate.opsForValue().get(redisTokenKey);
		if (StringUtil.isNotEmpty(token)) {
			return token;
		}
		DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/gettoken");
		OapiGettokenRequest request = new OapiGettokenRequest();
		request.setAppkey(appkey);
		request.setAppsecret(appSecret);
		request.setHttpMethod("GET");
		try {
			OapiGettokenResponse response = client.execute(request);
			if (response != null && response.getErrorCode().equals("0")) {
				token = response.getAccessToken();
				stringRedisTemplate.opsForValue().set(redisTokenKey, token, 7000, TimeUnit.SECONDS);
			}
		} catch (ApiException e) {
			log.error("获取钉钉接口调用凭证出错", e);
		}
		return token;
	}

	private String getUnionid(String code, String loginAppkey, String loginAppSecret) {
		String unionid = null;
		// 通过临时授权码获取授权用户的个人信息
		DefaultDingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/sns/getuserinfo_bycode");
		OapiSnsGetuserinfoBycodeRequest reqBycodeRequest = new OapiSnsGetuserinfoBycodeRequest();
		// 通过扫描二维码，跳转指定的redirect_uri后，向url中追加的code临时授权码
		reqBycodeRequest.setTmpAuthCode(code);
		try {
			OapiSnsGetuserinfoBycodeResponse bycodeResponse = client.execute(reqBycodeRequest, loginAppkey, loginAppSecret);
			if (bycodeResponse != null && bycodeResponse.isSuccess() && bycodeResponse.getErrorCode().equals("0")) {
				unionid = bycodeResponse.getUserInfo().getUnionid();
			}
		} catch (ApiException e) {
			log.error("获取钉钉用户标识失败：{}", e);
		}
		return unionid;
	}

	/**
	 * @Description: 获取钉钉用户标识
	 * @param: unionid
	 * @param: token
	 * @author: malin
	 * @date: 2021年3月9日 下午2:33:39
	 */
	private String getUserId(String unionid, String token) {
		String userId = null;
		// 根据unionid获取userid
		DingTalkClient clientDingTalkClient = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/user/getbyunionid");
		OapiUserGetbyunionidRequest reqGetbyunionidRequest = new OapiUserGetbyunionidRequest();
		reqGetbyunionidRequest.setUnionid(unionid);
		try {
			OapiUserGetbyunionidResponse oapiUserGetbyunionidResponse = clientDingTalkClient.execute(reqGetbyunionidRequest, token);
			log.info("oapiUserGetbyunionidResponse:{}", JSON.toJSONString(oapiUserGetbyunionidResponse));
			if (oapiUserGetbyunionidResponse != null && oapiUserGetbyunionidResponse.isSuccess() && oapiUserGetbyunionidResponse.getErrorCode().equals("0")) {
				userId = oapiUserGetbyunionidResponse.getResult().getUserid();
			}
		} catch (ApiException e) {
			log.error("获取钉钉用户标识失败：{}", e);
		}
		return userId;
	}

	/**
	 * @Description: 获取钉钉用户信息
	 * @param: userId
	 * @author: malin
	 * @date: 2021年3月9日 下午2:47:34
	 */
	private UserGetResponse getUserGetResponse(String userId, String token) {
		DingTalkClient clientDingTalkClient2 = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/v2/user/get");
		OapiV2UserGetRequest reqGetRequest = new OapiV2UserGetRequest();
		reqGetRequest.setUserid(userId);
		reqGetRequest.setLanguage("zh_CN");
		try {
			OapiV2UserGetResponse rspGetResponse = clientDingTalkClient2.execute(reqGetRequest, token);
			if (rspGetResponse != null && rspGetResponse.isSuccess() && rspGetResponse.getErrorCode().equals("0")) {
				return rspGetResponse.getResult();
			}
		} catch (ApiException e) {
			log.error("获取钉钉用户信息失败：{}", e);
		}
		return null;
	}

}
